﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.IO.IsolatedStorage;

namespace TfsCommitMonitor
{
	internal class Configuration : IEquatable<Configuration>, ICloneable
	{
		#region Constants
		internal static readonly String AppConfigPath =
			Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "TfsCommitMonitor");

		internal static readonly String DebugFilePath =
			Path.Combine(AppConfigPath, "DebugLog.txt");

		internal static readonly String TempFolderName = "TfsCommitMonitor";
		
		private static String _isolatedProjectCollectionFileName = "TfsCommitMonitor_Store.xml";
		public static String IsolatedProjectCollectionFileName
		{
			get { return _isolatedProjectCollectionFileName; }
		}
		private static String _isolatedConfigFileName = "TfsCommitMonitor_Config.xml";
		public static String IsolatedConfigFileName
		{
			get { return _isolatedConfigFileName; }
		}
		#endregion

		#region Singleton
		private Configuration() { }

		private static readonly object _lock = new object();

		private static Configuration _instance;
		[XmlIgnore]
		internal static Configuration Instance
		{
			get
			{
				lock (_lock)
				{
					if (_instance == null && HasPersistedData)
						_instance = LoadFromDisk();

					return _instance ?? (_instance = DefaultConfig);
				}
			}
		}
		#endregion

		internal Int32 MaxChangesToPersist { get; set; }

		internal Int32 MaxNumberOfChangesetsOnInitialLoad { get; set; }

		#region Default Config
		private static Configuration DefaultConfig
		{
			get
			{
				return new Configuration
				{
					MaxChangesToPersist = 1000,
					MaxNumberOfChangesetsOnInitialLoad = 30,
				};
			}
		}
		#endregion

		#region Instance Persistance
		public void PersistToDisk()
		{
			using (var sw = new StreamWriter(GetIsolatedStorageWriteStream(IsolatedConfigFileName)))
				sw.Write(Instance.Serialize());			
		}

		private static Configuration LoadFromDisk()
		{
			using (var sr = new StreamReader(GetIsolatedStorageReadStream(IsolatedConfigFileName)))
				return sr.ReadToEnd().Deserialize<Configuration>();
		}

		private static Boolean HasPersistedData
		{
			get { return IsolatedStorageFile.GetUserStoreForAssembly().FileExists(IsolatedConfigFileName); }
		}
		#endregion

		#region General Persistance
		internal static IsolatedStorageFileStream GetIsolatedStorageWriteStream(String fileName)
		{
			return
				new IsolatedStorageFileStream(
					fileName,
					FileMode.Create,
					FileAccess.Write,
					IsolatedStorageFile.GetUserStoreForAssembly());
		}

		internal static IsolatedStorageFileStream GetIsolatedStorageReadStream(String fileName)
		{
			return
				new IsolatedStorageFileStream(
					fileName,
					FileMode.Open,
					FileAccess.Read,
					IsolatedStorageFile.GetUserStoreForAssembly());
		}
		#endregion

		#region Clone Members
		internal Configuration Clone()
		{
			return 
				new Configuration
				{
					MaxChangesToPersist = this.MaxChangesToPersist,
					MaxNumberOfChangesetsOnInitialLoad = this.MaxNumberOfChangesetsOnInitialLoad,
				};
		}

		Object ICloneable.Clone()
		{
			return Clone();
		}

		#endregion

		public override Boolean Equals(Object obj)
		{
			return 
				Equals(obj as Configuration);
		}

		public override Int32 GetHashCode()
		{
			return
				MaxChangesToPersist.GetHashCode()
				^
				MaxNumberOfChangesetsOnInitialLoad.GetHashCode();
		}

		#region IEquatable<Configuration> Members

		public Boolean Equals(Configuration other)
		{
			return
				other != null
				&&
				MaxChangesToPersist == other.MaxChangesToPersist
				&&
				MaxNumberOfChangesetsOnInitialLoad == other.MaxNumberOfChangesetsOnInitialLoad;
		}

		#endregion
	}
}
